﻿using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Windows.Forms;
using Microsoft.AspNet.SignalR.Client;

namespace PerformanceTestOnClient
{
    public partial class Form2 : Form
    {
        const string ServerURI = "http://localhost:9001/default";
        private IList<HubConnection> connections = new List<HubConnection>();
        private Dictionary<string, IHubProxy> hubProxies = new Dictionary<string, IHubProxy>();
        private static  object _lock = new object();

        public Form2()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            int howMany = 1;
            if (int.TryParse(textBox1.Text, out howMany))
            {
                for (int i = 0; i < howMany; i++)
                {
                    ThreadPool.QueueUserWorkItem(x => ConnectAsync(Convert.ToInt32(x)), i);
                }
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            foreach (var hubProxy in hubProxies)
            {
                ThreadPool.QueueUserWorkItem(x =>
                {
                    lock (_lock)
                    {
                        var proxy = (KeyValuePair<string, IHubProxy>)x;
                        proxy.Value.Invoke("Send", hubProxy.Key, $"message from {proxy.Key}");
                    }
                }, hubProxy);
            }
        }

        private async void ConnectAsync(int index)
        {
            HubConnection Connection = new HubConnection(ServerURI);
            Connection.Closed += Connection_Closed;
            IHubProxy HubProxy = Connection.CreateHubProxy("MyHub");
            //Handle incoming event from server: use Invoke to write to console from SignalR's thread
            HubProxy.On<string, string>("AddMessage", (name, message) =>
                this.Invoke((Action)(() =>
                    RichTextBoxConsole.AppendText(String.Format("{0}: {1}" + Environment.NewLine, name, message))
                ))
            );
            try
            {
                await Connection.Start();
            }
            catch (HttpRequestException)
            {
                StatusText.Text = "Unable to connect to server: Start server before connecting clients.";
                //No connection: Don't enable Send button or show chat UI
                return;
            }

            this.Invoke((Action)(() =>
            {
                RichTextBoxConsole.AppendText($"Connection {index} linked to " + ServerURI + Environment.NewLine);
                RichTextBoxConsole.ScrollToCaret();
            }));

            connections.Add(Connection);
            hubProxies.Add("Connection" + index, HubProxy);
        }

        private void Connection_Closed()
        {
            //Deactivate chat UI; show login UI. 
            this.Invoke((Action)(() => StatusText.Text = "You have been disconnected."));
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            StopConnection();
        }

        private void StopConnection()
        {
            foreach (var connection in connections)
            {
                if (connection != null)
                {
                    connection.Stop();
                    connection.Dispose();
                }
            }
            connections.Clear();
            hubProxies.Clear();
            this.Invoke((Action)(() => RichTextBoxConsole.Text = ""));
        }

        private void button3_Click(object sender, EventArgs e)
        {
            StopConnection();
        }
    }
}
